/*     */ package com.zimbra.cs.imap;
/*     */ 
/*     */ import com.google.common.annotations.VisibleForTesting;
/*     */ import com.google.common.collect.Sets;
/*     */ import com.zimbra.client.ZFolder;
/*     */ import com.zimbra.client.ZMailbox;
/*     */ import com.zimbra.common.mime.shim.JavaMailInternetAddress;
/*     */ import com.zimbra.common.mime.shim.JavaMailInternetHeaders;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.util.ByteUtil;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.Pair;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.mailbox.DeliveryOptions;
/*     */ import com.zimbra.cs.mailbox.Flag;
/*     */ import com.zimbra.cs.mailbox.Folder;
/*     */ import com.zimbra.cs.mailbox.Mailbox;
/*     */ import com.zimbra.cs.mailbox.Message;
/*     */ import com.zimbra.cs.mailbox.Tag;
/*     */ import com.zimbra.cs.mime.ParsedMessage;
/*     */ import com.zimbra.cs.service.util.ItemId;
/*     */ import com.zimbra.cs.store.Blob;
/*     */ import com.zimbra.cs.store.BlobBuilder;
/*     */ import com.zimbra.cs.store.StoreManager;
/*     */ import com.zimbra.cs.util.AccountUtil;
/*     */ import java.io.BufferedInputStream;
/*     */ import java.io.IOException;
/*     */ import java.io.InputStream;
/*     */ import java.text.ParseException;
/*     */ import java.util.ArrayList;
/*     */ import java.util.Arrays;
/*     */ import java.util.Date;
/*     */ import java.util.Iterator;
/*     */ import java.util.List;
/*     */ import java.util.Set;
/*     */ import javax.mail.MessagingException;
/*     */ import javax.mail.internet.InternetAddress;
/*     */ import javax.mail.internet.InternetHeaders;
/*     */ import javax.mail.internet.MailDateFormat;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ final class AppendMessage
/*     */ {
/*     */   final ImapHandler handler;
/*     */   final String tag;
/*     */   private Date date;
/*     */   private boolean catenate;
/*     */   private List<Part> parts;
/*     */   private Blob content;
/*     */   private List<String> flagNames;
/*     */   private List<String> persistentFlagNames;
/*  69 */   private int flags = Flag.BITMASK_UNREAD;
/*  70 */   private final Set<String> tags = Sets.newHashSetWithExpectedSize(3);
/*     */   private short sflags;
/*     */   
/*     */   Blob getContent() throws IOException, ImapException, ServiceException {
/*  74 */     if (this.content == null) {
/*  75 */       this.content = (this.catenate ? doCatenate() : ((Part)this.parts.get(0)).literal.getBlob());
/*     */     }
/*  77 */     return this.content;
/*     */   }
/*     */   
/*     */   Date getDate() {
/*  81 */     return this.date;
/*     */   }
/*     */   
/*     */   List<String> getPersistentFlagNames() {
/*  85 */     return this.persistentFlagNames;
/*     */   }
/*     */   
/*     */   List<Part> getParts() {
/*  89 */     return this.parts;
/*     */   }
/*     */   
/*     */   static AppendMessage parse(ImapHandler handler, String tag, ImapRequest req) throws ImapParseException, IOException
/*     */   {
/*  94 */     AppendMessage append = new AppendMessage(handler, tag);
/*  95 */     append.parse(req);
/*  96 */     return append;
/*     */   }
/*     */   
/*     */   private AppendMessage(ImapHandler handler, String tag) {
/* 100 */     this.handler = handler;
/* 101 */     this.tag = tag;
/*     */   }
/*     */   
/*     */   private void parse(ImapRequest req) throws ImapParseException, IOException {
/* 105 */     if (req.peekChar() == 40) {
/* 106 */       this.persistentFlagNames = (this.flagNames = req.readFlags());
/* 107 */       req.skipSpace();
/*     */     }
/* 109 */     if (req.peekChar() == 34) {
/* 110 */       this.date = req.readDate(true, true);
/* 111 */       req.skipSpace();
/*     */     }
/* 113 */     if (((req.peekChar() == 99) || (req.peekChar() == 67)) && (this.handler.extensionEnabled("CATENATE"))) {
/* 114 */       req.skipAtom("CATENATE");
/* 115 */       req.skipSpace();
/* 116 */       req.skipChar('(');
/* 117 */       this.catenate = true;
/* 118 */       this.parts = new ArrayList(5);
/* 119 */       while (req.peekChar() != 41) {
/* 120 */         if (!this.parts.isEmpty()) {
/* 121 */           req.skipSpace();
/*     */         }
/* 123 */         String type = req.readATOM();
/* 124 */         req.skipSpace();
/* 125 */         if (type.equals("TEXT")) {
/* 126 */           this.parts.add(new Part(req.readLiteral()));
/* 127 */         } else if (type.equals("URL")) {
/* 128 */           this.parts.add(new Part(new ImapURL(this.tag, this.handler, req.readAstring())));
/*     */         } else {
/* 130 */           throw new ImapParseException(this.tag, "unknown CATENATE cat-part: " + type);
/*     */         }
/*     */       }
/* 133 */       req.skipChar(')');
/*     */     } else {
/* 135 */       this.parts = Arrays.asList(new Part[] { new Part(req.readLiteral8()) });
/*     */     }
/*     */   }
/*     */   
/*     */   @VisibleForTesting
/*     */   public AppendMessage(List<String> flagNames, Date date, List<Part> parts) {
/* 141 */     this.flagNames = (this.persistentFlagNames = flagNames);
/* 142 */     this.date = date;
/* 143 */     this.parts = parts;
/* 144 */     this.tag = null;
/* 145 */     this.handler = null;
/*     */   }
/*     */   
/*     */   void checkFlags(Mailbox mbox, ImapFlagCache flagSet, ImapFlagCache tagSet, List<Tag> newTags) throws ServiceException
/*     */   {
/* 150 */     if (this.flagNames == null) {
/* 151 */       return;
/*     */     }
/* 153 */     for (String name : this.flagNames) {
/* 154 */       ImapFlagCache.ImapFlag i4flag = flagSet.getByImapName(name);
/* 155 */       if ((i4flag != null) && (!i4flag.mListed)) {
/* 156 */         i4flag = null;
/* 157 */       } else if ((i4flag == null) && (!name.startsWith("\\"))) {
/* 158 */         i4flag = tagSet.getByImapName(name);
/*     */       }
/*     */       
/* 161 */       if (i4flag == null)
/*     */       {
/* 163 */         this.tags.add(name);
/*     */       }
/*     */       
/* 166 */       if (i4flag != null) {
/* 167 */         if (!i4flag.mPermanent) {
/* 168 */           this.sflags = ((short)(int)(this.sflags | i4flag.mBitmask));
/* 169 */         } else if (i4flag.mId > 0) {
/* 170 */           this.tags.add(i4flag.mName);
/* 171 */         } else if (i4flag.mPositive) {
/* 172 */           this.flags = ((int)(this.flags | i4flag.mBitmask));
/*     */         } else {
/* 174 */           this.flags = ((int)(this.flags & (i4flag.mBitmask ^ 0xFFFFFFFFFFFFFFFF)));
/*     */         }
/*     */       }
/*     */     }
/* 178 */     this.flagNames = null;
/*     */   }
/*     */   
/*     */   int storeContent(Object mboxObj, Object folderObj) throws ImapSessionClosedException, IOException, ServiceException
/*     */   {
/*     */     try {
/* 184 */       checkDate(this.content);
/* 185 */       int i; if ((mboxObj instanceof Mailbox)) {
/* 186 */         return store((Mailbox)mboxObj, (Folder)folderObj);
/*     */       }
/* 188 */       return store((ZMailbox)mboxObj, (ZFolder)folderObj);
/*     */     }
/*     */     finally {
/* 191 */       cleanup();
/*     */     }
/*     */   }
/*     */   
/*     */   private int store(Mailbox mbox, Folder folder) throws ImapSessionClosedException, ServiceException, IOException {
/* 196 */     boolean idxAttach = mbox.attachmentsIndexingEnabled();
/* 197 */     Long receivedDate = this.date != null ? Long.valueOf(this.date.getTime()) : null;
/* 198 */     ParsedMessage pm = new ParsedMessage(this.content, receivedDate, idxAttach);
/*     */     try {
/* 200 */       if (!pm.getSender().isEmpty()) {
/* 201 */         InternetAddress ia = new JavaMailInternetAddress(pm.getSender());
/* 202 */         if (AccountUtil.addressMatchesAccountOrSendAs(mbox.getAccount(), ia.getAddress())) {
/* 203 */           this.flags |= Flag.BITMASK_FROM_ME;
/*     */         }
/*     */       }
/*     */     }
/*     */     catch (Exception e) {}
/* 208 */     DeliveryOptions dopt = new DeliveryOptions().setFolderId(folder).setNoICal(true).setFlags(this.flags).setTags(this.tags);
/* 209 */     Message msg = mbox.addMessage(this.handler.getContext(), pm, dopt, null);
/* 210 */     if ((msg != null) && (this.sflags != 0) && (this.handler.getState() == ImapHandler.State.SELECTED)) {
/* 211 */       ImapFolder selectedFolder = this.handler.getSelectedFolder();
/*     */       
/*     */ 
/* 214 */       if (selectedFolder != null) {
/* 215 */         ImapMessage i4msg = selectedFolder.getById(msg.getId());
/* 216 */         if (i4msg != null) {
/* 217 */           i4msg.setSessionFlags(this.sflags, selectedFolder);
/*     */         }
/*     */       }
/*     */     }
/* 221 */     return msg == null ? -1 : msg.getId();
/*     */   }
/*     */   
/*     */   private int store(ZMailbox mbox, ZFolder folder) throws IOException, ServiceException {
/* 225 */     InputStream is = this.content.getInputStream();
/* 226 */     String id = mbox.addMessage(folder.getId(), Flag.toString(this.flags), null, this.date.getTime(), is, this.content.getRawSize(), true);
/* 227 */     return new ItemId(id, getCredentials().getAccountId()).getId();
/*     */   }
/*     */   
/*     */   void checkContent() throws IOException, ImapException, ServiceException {
/* 231 */     getContent();
/* 232 */     long size = this.content.getRawSize();
/* 233 */     long maxMsgSize = this.handler.getConfig().getMaxMessageSize();
/* 234 */     if ((maxMsgSize != 0L) && (size > this.handler.getConfig().getMaxMessageSize())) {
/* 235 */       cleanup();
/* 236 */       if (this.catenate) {
/* 237 */         throw new ImapParseException(this.tag, "TOOBIG", "maximum message size exceeded", false);
/*     */       }
/* 239 */       throw new ImapParseException(this.tag, "maximum message size exceeded", true);
/*     */     }
/* 241 */     if (size <= 0L) {
/* 242 */       throw new ImapParseException(this.tag, "zero-length message", false);
/*     */     }
/*     */   }
/*     */   
/*     */   private Blob doCatenate() throws IOException, ImapException, ServiceException
/*     */   {
/* 248 */     BlobBuilder bb = StoreManager.getInstance().getBlobBuilder();
/*     */     try {
/* 250 */       for (Part part : this.parts) {
/* 251 */         copyBytes(part.getInputStream(), bb);
/* 252 */         part.cleanup(); }
/*     */       Iterator i$;
/* 254 */       Part part; return bb.finish();
/*     */     } finally {
/* 256 */       for (Part part : this.parts) {
/* 257 */         part.cleanup();
/*     */       }
/* 259 */       this.parts = null;
/*     */     }
/*     */   }
/*     */   
/*     */   void cleanup() {
/* 264 */     if (this.content != null) {
/* 265 */       StoreManager.getInstance().quietDelete(this.content);
/* 266 */       this.content = null;
/*     */     }
/*     */   }
/*     */   
/*     */   private void copyBytes(InputStream is, BlobBuilder bb) throws IOException {
/*     */     try {
/* 272 */       bb.append(is);
/*     */     } finally {
/* 274 */       ByteUtil.closeStream(is);
/*     */     }
/*     */   }
/*     */   
/*     */   private void checkDate(Blob blob) throws IOException, ServiceException
/*     */   {
/* 280 */     if ((this.date == null) && (getCredentials().isHackEnabled(ImapCredentials.EnabledHack.THUNDERBIRD))) {
/* 281 */       this.date = getSentDate(blob);
/*     */     }
/*     */     
/*     */ 
/*     */ 
/* 286 */     if ((this.date != null) && (this.date.getTime() > 2147483647000L)) {
/* 287 */       ZimbraLog.imap.info("APPEND failed: date out of range");
/* 288 */       throw ServiceException.FAILURE("APPEND failed (date out of range)", null);
/*     */     }
/*     */   }
/*     */   
/*     */   private static Date getSentDate(Blob content) throws IOException {
/* 293 */     InputStream is = new BufferedInputStream(content.getInputStream());
/*     */     try
/*     */     {
/* 296 */       return getSentDate(new JavaMailInternetHeaders(is));
/*     */     } catch (MessagingException e) {
/* 298 */       return null;
/*     */     } finally {
/* 300 */       ByteUtil.closeStream(is);
/*     */     }
/*     */   }
/*     */   
/*     */   static Date getSentDate(InternetHeaders ih) {
/* 305 */     String s = ih.getHeader("Date", null);
/* 306 */     if (s != null) {
/*     */       try {
/* 308 */         return new MailDateFormat().parse(s);
/*     */       } catch (ParseException pex) {
/* 310 */         return null;
/*     */       }
/*     */     }
/* 313 */     return null;
/*     */   }
/*     */   
/*     */   private ImapCredentials getCredentials() {
/* 317 */     return this.handler.getCredentials();
/*     */   }
/*     */   
/*     */   final class Part
/*     */   {
/*     */     Literal literal;
/*     */     ImapURL url;
/*     */     
/*     */     Part(Literal literal) {
/* 326 */       this.literal = literal;
/*     */     }
/*     */     
/*     */     Part(ImapURL url) {
/* 330 */       this.url = url;
/*     */     }
/*     */     
/*     */     InputStream getInputStream() throws IOException, ImapException {
/* 334 */       if (this.literal != null) {
/* 335 */         return this.literal.getInputStream();
/*     */       }
/* 337 */       return (InputStream)this.url.getContentAsStream(AppendMessage.this.handler, AppendMessage.this.handler.getCredentials(), AppendMessage.this.tag).getSecond();
/*     */     }
/*     */     
/*     */     void cleanup()
/*     */     {
/* 342 */       if (this.literal != null) {
/* 343 */         this.literal.cleanup();
/*     */       }
/*     */     }
/*     */     
/*     */     Literal getLiteral() {
/* 348 */       return this.literal;
/*     */     }
/*     */     
/*     */     ImapURL getUrl() {
/* 352 */       return this.url;
/*     */     }
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/cs/imap/AppendMessage.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */